package com.ly.mpayment.persist.service.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.protocol.HTTP;
import org.apache.http.util.EntityUtils;
import org.apache.log4j.Logger;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.thoughtworks.xstream.XStream;

import net.sf.json.JSONObject;

/**
 * Created by hadoop on 2016/6/29.
 */
public class WechatUtil {

	private static final String appId = "wxe0d2436b67e68c53";
	private static final String appSecret = "d221fba22a77e7a7ebc9b640629b58b0";
	private static final String EncodingAESKey = "tQPAiHfqLlygYGQnBtETDL5MchKjGFddMZSxzf6H1JV";

	private static final String templateId = "cQ-9X5tsfYYn5OHiStGup4EYCB1CP0ROiGrUvbfHMzo";
	static Logger logger = Logger.getLogger(WechatUtil.class);
	/**
	 * https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&
	 * appid=wx10f06daffd439dd0&secret=95c6e3340ab9f093f425d21e40812245 200 OK
	 * Connection: close Date: Thu, 04 Aug 2016 11:32:26 GMT Content-Type:
	 * application/json; encoding=utf-8 Content-Length: 175 { "access_token":
	 * "P1gEdObqBSsZe3j7zU5farUkY2d6Wfa-0Lp1-lmWQgV7mWOwMPz3Ey8OnhjmejnleJCKz5n7lR04uK_McnizVBE023c1pIMM7Dtqta0ZFijlqPah6ulMxzH85j-Y6RR8AEYeAEAMQK",
	 * "expires_in": 7200 }
	 */
	private static final String getTokenUrl = "https://api.weixin.qq.com/cgi-bin/token?";

	// 设置所属行业地址 详见参数说明
	/**
	 * { "industry_id1":"1", "industry_id2":"4" }
	 */
	private static final String setIndustry = "https://api.weixin.qq.com/cgi-bin/template/api_set_industry?access_token=";

	// 获取设置行业信息
	/**
	 * { "primary_industry":{"first_class":"运输与仓储","second_class":"快递"},
	 * "secondary_industry":{"first_class":"IT科技","second_class":"互联网|电子商务"} }
	 */
	private static final String getIndustry = "https://api.weixin.qq.com/cgi-bin/template/get_industry?access_token=";

	// 获取模板id地址
	/**
	 * in{ "template_id_short":"TM00015" } out { "errcode":0, "errmsg":"ok",
	 * "template_id":"Doclyl5uP7Aciu-qZ7mJNPtWkbkYnWBWVja26EGbNyk" }
	 */
	private static final String templateIdUrl = "https://api.weixin.qq.com/cgi-bin/template/api_add_template?access_token=";
	// 获取模板列表地址
	/**
	 * { "template_list": [{ "template_id":
	 * "iPk5sOIt5X_flOVKn5GrTFpncEYTojx6ddbt8WYoV5s", "title": "领取奖金提醒",
	 * "primary_industry": "IT科技", "deputy_industry": "互联网|电子商务", "content":
	 * "{ {result.DATA} }\n\n领奖金额:{ {withdrawMoney.DATA} }\n领奖  时间:{ {withdrawTime.DATA} }\n银行信息:{ {cardInfo.DATA} }\n到账时间:  { {arrivedTime.DATA} }\n{ {remark.DATA} }"
	 * , "example":
	 * "您已提交领奖申请\n\n领奖金额：xxxx元\n领奖时间：2013-10-10 12:22:22\n银行信息：xx银行(尾号xxxx)\n到账时间：预计xxxxxxx\n\n预计将于xxxx到达您的银行卡"
	 * }] }
	 */
	public static final String getAllTemplateUrl = "https://api.weixin.qq.com/cgi-bin/template/get_all_private_template?access_token=";

	// 发送模板消息
	/**
	 * { "touser":"OPENID",
	 * "template_id":"ngqIpbwh8bUfcSsECmogfXcV14J0tQlEpBO27izEYtY",
	 * "url":"http://weixin.qq.com/download", "data":{ "first": {
	 * "value":"恭喜你购买成功！", "color":"#173177" }, "keynote1":{ "value":"巧克力",
	 * "color":"#173177" }, "keynote2": { "value":"39.8元", "color":"#173177" },
	 * "keynote3": { "value":"2014年9月22日", "color":"#173177" }, "remark":{
	 * "value":"欢迎再次购买！", "color":"#173177" } } }
	 */
	public static final String sendTemplateMessage = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=";

	private static String accessToken = null;

	public static Map<String, String> xmlToMap(HttpServletRequest request) throws IOException, DocumentException {
		Map<String, String> map = new HashMap();
		SAXReader saxReader = new SAXReader();
		InputStream in = request.getInputStream();
		Document document = saxReader.read(in);
		Element root = document.getRootElement();
		List<Element> list = root.elements();
		for (Element e : list) {
			map.put(e.getName(), e.getText());
		}
		in.close();
		return map;
	}

	/**
	 * 获取微信openid
	 *
	 * @param code
	 * @return
	 */
	public static String getOpenId(String code) {
		String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret
				+ "&code=" + code + "&grant_type=authorization_code";
		try {
			String openId = httpGet(url);
			logger.info("openid:------------->:" + openId);
			return openId;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	public static String objectToXml(BaseMessage message) {
		XStream xStream = new XStream();
		xStream.alias("xml", message.getClass());
		return xStream.toXML(message);
	}

	/**
	 * http 请求方法 返回请求结果， null 则为请求失败
	 *
	 * @param url
	 * @return
	 * @throws IOException
	 * @throws ClientProtocolException
	 */
	@SuppressWarnings({ "unused", "resource", "deprecation" })
	private static String httpGet(String url) throws ClientProtocolException, IOException {
		HttpClient httpClient = new DefaultHttpClient();
		HttpGet httpGet = new HttpGet(url);
		HttpResponse response = httpClient.execute(httpGet);
		int statusCode = response.getStatusLine().getStatusCode();
		if (statusCode == HttpStatus.SC_OK) {
			// openid:------------->: 返回数据格式
			// {"access_token":"WmQWOhssurDLMymrzx_S3xV9Drm4nhzPYGDZEC3Y3dFere8PfhGK8Bquf7ReZCepsoX2v_ymhzNWSZ-V--kB6zqTv2KjnaMR9BjHQajNBtk",
			// "expires_in":7200,
			// "refresh_token":"DH7GSev1ZWUmxrxzz_YlP91fEXWDefSjI3T5Jlj1lwaTeLMO2AssoEMYM_iUxUnEf8FY24DE7acKiAwkCTrVW5lSSt4tmAuhMeZ3ZpbnqQI",
			// "openid":"o0JSAwuM4Sqn1a4IzjowC1G36op4","scope":"snsapi_base"}
			JSONObject json = JSONObject.fromObject(EntityUtils.toString(response.getEntity(), HTTP.UTF_8));
			if (json.containsKey("openid") && json.containsKey("access_token")) {
				logger.info("accessToken:--->set:" + accessToken);
				return json.getString("openid");
			}

		}
		return null;
	}

	public static String obtainAccessToken() throws IOException {
		HttpClient httpClient = new DefaultHttpClient();
		HttpGet httpGet = new HttpGet(
				getTokenUrl + "grant_type=client_credential&appid=" + appId + "&secret=" + appSecret);
		HttpResponse response = httpClient.execute(httpGet);
		int statusCode = response.getStatusLine().getStatusCode();
		if (statusCode == HttpStatus.SC_OK) {
			String result = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
			if (result != null) {
				JSONObject jsonObject = JSONObject.fromObject(result);
				if (jsonObject.containsKey("access_token")) {
					String accessToken = jsonObject.getString("access_token");
					if (accessToken != null) {
						return accessToken;
					}
				}
				// String expires_in = jsonObject.getString("expires_in");
			}

		}
		return null;
	}

	/**
	 * @param openId
	 *            推送对象的微信openId
	 * @param first
	 *            模板消息的标题内容
	 * @param name
	 *            baby的名字
	 * @param time
	 *            刷卡时间
	 * @param location
	 *            刷卡地点
	 * @param remark
	 *            结束语
	 * @param maxTimes
	 *            最大请求次数,至少2次
	 * @throws IOException
	 */
	@SuppressWarnings({ "resource", "deprecation" })
	public static void sendTemplateMessage(String openId,  JSONObject data)
			throws IOException {
		HttpClient httpClient = new DefaultHttpClient();
		logger.info("accessToken:--->" + accessToken);
		if (accessToken == null) {
			accessToken = obtainAccessToken();
		}
		logger.info("accessToken:--->" + accessToken);

		JSONObject jsonObject = new JSONObject();
		jsonObject.put("touser", openId);
		jsonObject.put("template_id", templateId);

		jsonObject.put("data", data);
		logger.info(sendTemplateMessage + accessToken);
		HttpPost httpPost = new HttpPost(sendTemplateMessage + accessToken);
		httpPost.addHeader("Content-Type", "application/json");
		logger.info(jsonObject.toString());
		httpPost.setEntity(new StringEntity(jsonObject.toString(), HTTP.UTF_8));
		HttpResponse response = httpClient.execute(httpPost);
		if (response.getStatusLine().getStatusCode() == 200) {
			String result = EntityUtils.toString(response.getEntity(), HTTP.UTF_8);
			logger.info(result);
			if (result != null) {
				JSONObject job = JSONObject.fromObject(result);
				if (job.containsKey("errcode")) {
					int errcode = job.getInt("errcode");
					switch (errcode) {
					case 0: // 成功
						return;
					case 40014:
					case 40001:
					case 42001:// access_token不合法或超时，如过期
						System.out.println("access_token不合法，如过期,重新获取token");
						accessToken = obtainAccessToken();
						sendTemplateMessage(openId, data);
						break;
					default:// 其他错误再发一次
						logger.info("-------->"+result);
						//sendTemplateMessage(openId, data);
						break;
					}
				}
			}
		} else {
			System.err.println("微信服务器异常");
		}
	}

//	/**
//	 * 发送https请求
//	 *
//	 * @param requestUrl
//	 *            请求地址
//	 * @param requestMethod
//	 *            请求方式（GET、POST）
//	 * @param outputStr
//	 *            提交的数据
//	 * @return JSONObject(通过JSONObject.get(key)的方式获取json对象的属性值)
//	 */
//	public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) {
//		JSONObject jsonObject = null;
//		try {
//			// 创建SSLContext对象，并使用我们指定的信任管理器初始化
//			TrustManager[] tm = null;// { new MyX509TrustManager() };
//			SSLContext sslContext = SSLContext.getInstance("SSL", "SunJSSE");
//			sslContext.init(null, tm, new java.security.SecureRandom());
//			// 从上述SSLContext对象中得到SSLSocketFactory对象
//			SSLSocketFactory ssf = sslContext.getSocketFactory();
//			URL url = new URL(requestUrl);
//			HttpsURLConnection conn = (HttpsURLConnection) url.openConnection();
//			conn.setSSLSocketFactory(ssf);
//			conn.setDoOutput(true);
//			conn.setDoInput(true);
//			conn.setUseCaches(false);
//			// 设置请求方式（GET/POST）
//			conn.setRequestMethod(requestMethod);
//			// conn.setRequestProperty("content-type",
//			// "application/x-www-form-urlencoded");
//			// 当outputStr不为null时向输出流写数据
//			if (null != outputStr) {
//				OutputStream outputStream = conn.getOutputStream();
//				// 注意编码格式
//				outputStream.write(outputStr.getBytes("UTF-8"));
//				outputStream.close();
//			}
//			// 从输入流读取返回内容
//			InputStream inputStream = conn.getInputStream();
//			InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
//			BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
//			String str = null;
//			StringBuffer buffer = new StringBuffer();
//			while ((str = bufferedReader.readLine()) != null) {
//				buffer.append(str);
//			}
//			// 释放资源
//			bufferedReader.close();
//			inputStreamReader.close();
//			inputStream.close();
//			inputStream = null;
//			conn.disconnect();
//			jsonObject = JSONObject.fromObject(buffer.toString());
//		} catch (ConnectException ce) {
//			// log.error("连接超时：{}", ce);
//			ce.printStackTrace();
//		} catch (Exception e) {
//			// log.error("https请求异常：{}", e);
//			e.printStackTrace();
//		}
//		return jsonObject;
//	}

//	public static void main(String[] args) {
//		// try {
//		// String openId = "o0JSAwntVdc6xbomFzu7o5ByQvEQ";
//		// sendTemplateMessage(openId, "亲爱的小山山同学家长，小山山同学有一条考勤信息", "小山山",
//		// "2013年11月18日8时30分", "第一幼儿园", "谢谢您的关注", 3);
//		// } catch (IOException e) {
//		// e.printStackTrace();
//		// }
//		String phone = "18090037299";
//		System.out.println(isPhone(phone));
//	}
//
//	public static boolean isEmail(String input) {
//		Pattern pattern = Pattern
//				.compile("^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0-9A-Z]+)?\\.)" + "+[a-zA-Z]{2,}$");
//		Matcher matcher = pattern.matcher(input);
//		return matcher.matches();
//	}
//
//	public static boolean isPhone(String input) {
//		Pattern pattern = Pattern.compile("^((13[0-9])|(15[^4,\\\\D])|(18[0,5-9]))\\\\d{8}$");
//		Matcher matcher = pattern.matcher(input);
//		return matcher.matches();
//	}
}
